#include "app_buffer.h"
#include <stdlib.h>
#include <string.h>
#include "log/log.h"

static SubBuffer *subbuffer_init(int size){
    SubBuffer *sub_buffer = (SubBuffer *)malloc(sizeof(SubBuffer));
    sub_buffer->ptr = (char *)malloc(size);
    sub_buffer->size = size;
    sub_buffer->len = 0;

    return sub_buffer;
}

static void sub_buffer_swap(Buffer *buffer){
    // 加写锁
    pthread_mutex_lock(&buffer->write_mutex);

    // 交换缓冲区
    SubBuffer *tmp = buffer->sub_buffers[0];
    buffer->sub_buffers[0] = buffer->sub_buffers[1];
    buffer->sub_buffers[1] = tmp;

    // 解写锁
    pthread_mutex_unlock(&buffer->write_mutex);
}

Buffer *app_buffer_init(int size)
{
    // 初始化缓冲区
    Buffer *buffer = (Buffer *)malloc(sizeof(Buffer));

    buffer->sub_buffers[0] = subbuffer_init(size);
    buffer->sub_buffers[1] = subbuffer_init(size);
    buffer->read_index = 0;
    buffer->write_index = 1;

    // 初始化读写锁
    pthread_mutex_init(&buffer->read_mutex, NULL);
    pthread_mutex_init(&buffer->write_mutex, NULL);

    return buffer;
}

void app_buffer_free(Buffer *buffer)
{
    free(buffer->sub_buffers[buffer->read_index]->ptr);
    free(buffer->sub_buffers[buffer->write_index]->ptr);
    free(buffer->sub_buffers[buffer->read_index]);
    free(buffer->sub_buffers[buffer->write_index]);
    free(buffer);
}

int app_buffer_write(Buffer *buffer, char *data, int len)
{
    if (len > 255)
    {
        log_error("data len too long");
        return -1;
    }

    // 加写锁
    pthread_mutex_lock(&buffer->write_mutex);
    
    // 得到写缓冲区
    SubBuffer *write_buffer = buffer->sub_buffers[buffer->write_index];
    // 检查缓冲区是否足够
    if (write_buffer->size - write_buffer->len < len + 1)
    {
        log_error("buffer is full");
        // 解锁
        pthread_mutex_unlock(&buffer->write_mutex);
        return -1;
    }
    
    // 写入数据
    // 第一字节存放写入数据的长度，后面跟长度的数据
    write_buffer->ptr[write_buffer->len] = len;
    memcpy(write_buffer->ptr + write_buffer->len + 1, data, len);

    // 更新数据长度
    write_buffer->len += len + 1;

    // 解锁
    pthread_mutex_unlock(&buffer->write_mutex);

    return 0;
}

int app_buffer_read(Buffer *buffer, char *data_buf, int buf_size)
{
    // 加读锁
    pthread_mutex_lock(&buffer->read_mutex);

    // 得到读缓冲区
    SubBuffer *read_buffer = buffer->sub_buffers[buffer->read_index];
    if (read_buffer->len == 0)
    {
        sub_buffer_swap(buffer);
        read_buffer = buffer->sub_buffers[buffer->read_index];
        if (read_buffer->len == 0){
            log_error("buffer is empty");
            // 解锁
            pthread_mutex_unlock(&buffer->read_mutex);
            return -1;
        }
    }

    // 读取数据
    int len = read_buffer->ptr[0];
    if (len > buf_size){
        log_error("buffer size too small");
        // 解锁
        pthread_mutex_unlock(&buffer->read_mutex);
        return -1;
    }
    memcpy(data_buf, read_buffer->ptr + 1, len);
    // 移动后面的数据到前面
    memmove(read_buffer->ptr, read_buffer->ptr + len + 1, read_buffer->len - len - 1);

    // 更新数据长度
    read_buffer->len -= len + 1;

    // 解锁
    pthread_mutex_unlock(&buffer->read_mutex);

    return len;
}
